package com.cppsu.cgx.libraryseatselection.services.impl;

import com.cppsu.cgx.libraryseatselection.dao.SeatDao;
import com.cppsu.cgx.libraryseatselection.dto.AvailableSeatsParam;
import com.cppsu.cgx.libraryseatselection.dto.SeatParam;
import com.cppsu.cgx.libraryseatselection.entity.Floor;
import com.cppsu.cgx.libraryseatselection.entity.Seat;
import com.cppsu.cgx.libraryseatselection.entity.SeatSelection;
import com.cppsu.cgx.libraryseatselection.exception.ApiException;
import com.cppsu.cgx.libraryseatselection.mapper.*;
import com.cppsu.cgx.libraryseatselection.services.SeatService;
import org.mybatis.dynamic.sql.SqlBuilder;
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
import org.mybatis.dynamic.sql.render.RenderingStrategies;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static org.mybatis.dynamic.sql.SqlBuilder.*;

/**
 * @Author: guibo
 * @Description:
 * @Date: Created in 14:53 2021/3/10
 * @Modified By:
 */
@Service
public class SeatServiceImpl implements SeatService {
    @Autowired
    SeatMapper seatMapper;

    @Autowired
    SeatDao seatDao;

    @Autowired
    SeatSelectionMapper seatSelectionMapper;

    @Autowired
    LibraryMapper libraryMapper;

    @Autowired
    FloorMapper floorMapper;

    @Override
    public List<Seat> list(SeatParam seatParam) {
        return seatMapper.select(c->c
                .where(SeatDynamicSqlSupport.id,isEqualToWhenPresent(seatParam.getId()))
                .and(SeatDynamicSqlSupport.floorId,isEqualToWhenPresent(seatParam.getFloorId()))
                .and(SeatDynamicSqlSupport.number,isLikeWhenPresent(seatParam.getNumber()).then(s->"%"+s+"%"))
                .and(SeatDynamicSqlSupport.status,isEqualToWhenPresent(seatParam.getStatus()))
        );
    }

    @Override
    public int add(SeatParam seatParam) {
        List<Seat> seatList =  seatMapper.select(c->c
                .where(SeatDynamicSqlSupport.number,isEqualTo(seatParam.getNumber()))
                .and(SeatDynamicSqlSupport.floorId,isEqualTo(seatParam.getFloorId()))
        );
        if(!seatList.isEmpty())
            throw new ApiException("改座位已存在");
        Seat seat = new Seat();
        seatParam.setId(null);
        BeanUtils.copyProperties(seatParam,seat);
        return seatMapper.insertSelective(seat);
    }

    @Override
    public int update(SeatParam seatParam) {
        Seat seat = new Seat();
        BeanUtils.copyProperties(seatParam,seat);
        return seatMapper.updateByPrimaryKeySelective(seat);
    }

    @Override
    public int delete(List<Long> ids) {
        return seatMapper.delete(c->c.where(SeatDynamicSqlSupport.id,isIn(ids)));
    }

    @Override
    public List<Seat> listAvailableSeats(AvailableSeatsParam availableSeatsParam) {
        /*
        * 列出已经被选的座位*/
        List<SeatSelection> seatSelectionList =  seatSelectionMapper.select(c->c
                .where(SeatSelectionDynamicSqlSupport.start,isBetweenWhenPresent(availableSeatsParam.getStart())
                                .and(availableSeatsParam.getEnd())
                        ,or(SeatSelectionDynamicSqlSupport.end,isBetweenWhenPresent(availableSeatsParam.getStart())
                                .and(availableSeatsParam.getEnd())))
        );

        List<Long> seatIds = seatSelectionList.stream().map(SeatSelection::getSeatId).collect(Collectors.toList());
        return seatMapper.select(c->c.where(SeatDynamicSqlSupport.id,isNotIn(seatIds))
                .and(SeatDynamicSqlSupport.status,isEqualTo(1))
                .and(SeatDynamicSqlSupport.floorId,isEqualTo(availableSeatsParam.getFloorId()))
        );
    }

    @Override
    public int addBatch(Long floorId) {
        List<Seat> seatList = new ArrayList<>();
        Floor floor = floorMapper.selectByPrimaryKey(floorId).orElse(null);
        if(floor==null){
            throw new ApiException("提供的楼层不存在");
        }
        for(int i=1;i<=floor.getY();i++){
            for (int j=1;j<=floor.getX();j++){
                String seatNumberStr = i+"-"+j;
                Seat seat = new Seat();
                seat.setNumber(seatNumberStr);
                seat.setFloorId(floorId);
                seat.setStatus(1);
                seatList.add(seat);
            }

        }
        seatMapper.delete(c-> c.where(SeatDynamicSqlSupport.floorId,isEqualTo(floorId)));
        MultiRowInsertStatementProvider<Seat> seatMultiRowInsertStatement = SqlBuilder
                .insertMultiple(seatList)
                .into(SeatDynamicSqlSupport.seat)
                .map(SeatDynamicSqlSupport.number).toProperty("number")
                .map(SeatDynamicSqlSupport.floorId).toProperty("floorId")
                .map(SeatDynamicSqlSupport.status).toProperty("status")
                .build()
                .render(RenderingStrategies.MYBATIS3);
        return seatDao.insertMultiple(seatMultiRowInsertStatement);
    }

}
